﻿package {
	import org.flixel.*;
	
	/*
	 * Player is your avatar in this game, controling
	 * a space ship to kic some asses, in this class
	 * we create blast, shots and control de player ship
	 * animation
	 */
	public class Player extends Ship {
		/* The tree animations during flying */
        private static const FLYING_NORMAL:int = 0;
        private static const FLYING_DOWN:int = 1;
        private static const FLYING_UP:int = 2;

		/* Controls the arsenal */
		private static const MAX_BULLETS:int = 30;
		private static const MAX_BLAST_PARTICLES:int = 20;
        private static const MAX_CHARGES:int = 15;
        private static const BLAST_PRICE:int = 5;
        private static const CHARGE_PLUS:int = 1;
        private static const CHARGE_TIME:Number = 1;

		/* How many lifes you have */
		private var _tries:int = 0;
        public function getTries():int { return _tries; }

		/* Get the charges, and pass to HUD, but not here */
        private var _charges:int = MAX_CHARGES;
        public function getCharges():int { return _charges; }

		/* Recycler for bullets, blast, and timer to charge */
        private var _bullets:FlxRecycler = new FlxRecycler(MAX_BULLETS);
		private var _blast_particles:FlxRecycler = new FlxRecycler(3);
		
		/* Charges 1 per second */
		private var _charge_time:FlxTimer = new FlxTimer(1, chargeBlast);
		
		/* Flyind dir and last dir (to prevent repocessing) */
        private var _flying_dir:int = FLYING_NORMAL;
        private var _last_dir:int = FLYING_NORMAL;

		/* Born of a hero */
		public function Player(x:int, y:int) {
			super(x, y);
            configure();
            loadGraphics();
            createBullets();
            createParticles();
            createTimers();
		}

		/* Configures energy and default speed */
        private function configure():void {
            health = 1;
			_default_velocity = 150;
        }

		/* Load graphics, and configures the animations */
        private function loadGraphics():void {
            loadGraphic(Resources.player, true, false, 52, 21, true); 
            addAnimation("flying", [0,1,2], 10, true);
            addAnimation("flying_down", [3,4,5], 10, true);
            addAnimation("flying_up", [6,7,8], 10, true);
            play("flying");
        }

		/* Create the shoots and store in a recycler */
        private function createBullets():void {
            for(var i:int = 0;i <= MAX_BULLETS;i++) {
                var s:Shot = new Shot(0, 0);
				_bullets.add(s);
            }
        }

		/* Create particles emitters and store in recyclers too */
        private function createParticles():void {
            while(!_blast_particles.isMax()) {
                var p:FlxEmitter = new FlxEmitter();
                p.delay = 1;
                p.gravity = 0;
                p.maxRotation = 10;
                p.setXSpeed(500, 1000);
                p.setYSpeed(-300, 300);

                for(var i:int = 0;i < MAX_BLAST_PARTICLES;i++) {
                    var particle:FlxSprite = new FlxSprite();
                    particle.createGraphic(5, 5, 0xFFFFFF00);
                    particle.exists = false;
                    p.add(particle);
                }

                _blast_particles.add(p);
            }
        }

		/* Create timer, load the timer of charge bar */
        private function createTimers():void {
            _charge_time = FlxG.addTimer(_charge_time);
            _charge_time.start();
        }

		/* Charge a piece for second */
        private function chargeBlast():void {
            if(_charges < MAX_CHARGES) {
                _charges += CHARGE_PLUS;
                StatePlay(FlxG.state).hud.updateChargeBar(_charges);
            }
        }
		
		/* Test keys, configures animation, and test limits */
        override public function update():void {
			testKeys();
            setFlyngAnimation();
			super.update();	
			testBorderCollsions();
		}

		/* Test keys to move the ship */
		private function testKeys():void {
			
			/* Flying normal every time our ... */
            _flying_dir = FLYING_NORMAL;

			velocity.x = 0;
			velocity.y = 0;
			
			if(FlxG.keys.LEFT)
				velocity.x -= _default_velocity;
			else if(FlxG.keys.RIGHT)
				velocity.x += _default_velocity;			

			/* When UP or DOWN, changes the animation */
			if(FlxG.keys.UP) {
				velocity.y -= _default_velocity;
                _flying_dir = FLYING_UP;
            } else if(FlxG.keys.DOWN) {	
				velocity.y += _default_velocity;
                _flying_dir = FLYING_DOWN;
            }
	
			/* Shot our Blast */
			if(FlxG.keys.justPressed("C")) shot();
			if(FlxG.keys.justPressed("X")) blast();
		}
	
		/* Controls the shot */
        private function shot():void {
			/* Play shot sound */
            FlxG.play(Resources.shot);
			
			/* Adjust permits set where the shots
			 * come from in the current animation
			 */
            var adjust:int = 0;
            
            switch(_flying_dir) {
                case FLYING_NORMAL: adjust = 12; break;
                case FLYING_DOWN: adjust = 8; break;
                case FLYING_UP: adjust = 14; break;
            }

			/* For each shot take a sprite from the recycler */
			var s:FlxSprite = _bullets.getObject(x + 30, y + height - adjust) as FlxSprite;
			
			/* 
			 * This is important, here we are adding a sprite element 
			 * into the group in StatePlay, that's the way to reference
			 * a class in memory, and gets his properties, in this case
			 * add a current shot (s:Sprite) into group shot located in 
			 * state StatePlay
			 */
			StatePlay(FlxG.state).shot.add(s);
        }

		/* The blast is terrible */
        private function blast():void {
			/* If you have charge bar, to pay you will get the power */
            if (_charges >= BLAST_PRICE) {
				/* Play blast sound */
                FlxG.play(Resources.explosion_2);
				
				/* Gets the emitter from the recycler */
                var p:FlxEmitter = _blast_particles.getObject(0, 0) as FlxEmitter;
				
				/*
				 * Here we start and set wheres come from the blast, 
				 * blast at this (Player)
				 */
                p.start();
                p.at(this);
				
				/* Again add into StatePlay */
                StatePlay(FlxG.state).blast.add(p);
				
				/* Reduce the blast charge, is the price */
                _charges -= BLAST_PRICE;
				
				/* Configures the exibition of the charge */
                StatePlay(FlxG.state).hud.updateChargeBar(_charges);
				
				/* Avoids negative values in charge bar */
                if (_charges < 0) _charges = 0;
            }
        }

		/* Set the animation */
        private function setFlyngAnimation():void {
            if(_last_dir != _flying_dir) {
                switch(_flying_dir) {
                    case FLYING_NORMAL: play("flying"); break;
                    case FLYING_DOWN: play("flying_down"); break;
                    case FLYING_UP: play("flying_up"); break;
                }
            }
            _last_dir = _flying_dir;
        }

		/* Test the limits to ship don't go away from player's eyes */
		private function testBorderCollsions():void {
            if(x > FlxG.width - width)
                x = FlxG.width - width;
            else if(x < 0)
                x = 0

            if(y > FlxG.height - height)
                y = FlxG.height - height;
            else if(y < 0)
                y = 0
		}

        override public function kill():void {
			/* If you die play this */
			FlxG.play(Resources.explosion_2);
			super.kill();
		}

		/* Cleans the memory */
        override public function destroy():void {
            _bullets.destroy();
            _blast_particles.destroy();
            _charge_time.destroy();
            super.destroy();
        }
	}
}
